package com.ubercache;

import java.util.Set;

public class LruStrategy implements CacheStrategy {

    private boolean remove(CacheLevel src, CacheLevel target) {
        CacheEntry leastTime = null;
        Object leastKey = null;
        
        Set<Object> keys = src.getKeys();
        
        for (Object i : keys) {
            CacheEntry entry = src.getCachedEntry(i);
            
            if (entry == null) {
                continue;
            }
            
            if ((leastTime == null) || (entry.lastUse < leastTime.lastUse)) {
                leastTime = entry;
                leastKey = i;
            }
        }
        
        // no cached objects at all, interrupting.
        if (leastTime == null) {
            return false;
        }
        
        if (target != null) {
            String data = src.doGet(leastKey);
            
            if (data != null) {
                target.doPut(leastKey, data, leastTime);
            }
        }
        
        src.remove(leastKey);
        
        return true;
    }

    private void trim(CacheLevel src, CacheLevel target) {
        while (src.getSize() > src.getMaxSize()) {
            if (!remove(src, target)) {
                break;
            }
        }
    }
    
    @Override
    public void trimExcess(Cache cache) {
        CacheLevel level0 = cache.getLevel0();
        CacheLevel level1 = cache.getLevel1();
     
        trim(level0, level1);
        trim(level1, null);
    }
}